import { injectable, inject } from 'tsyringe';
import { UserServiceToken, IUserService } from '../../domain/interfaces/IUserService';
import { User } from '../../domain/entities/User';
import { hashPassword, verifyPassword, sign } from '../../utils/auth';
import { UserRepository } from '../../infrastructure/database/userRepository';
import { LoggerToken } from '../../domain/interfaces/ILogger';
import type { ILogger } from '../../domain/interfaces/ILogger';
import { UserStatus } from '../../domain/types/userTypes';

@injectable()
export class UserService implements IUserService {
  constructor(
    @inject(LoggerToken) private logger: ILogger,
    @inject(UserRepository) private userRepo: UserRepository
  ) {}

  async createUser(credentials: any) {
    const id = `user_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
    const hash = hashPassword(credentials.password);
    const user = new User(id, credentials.username, hash, UserStatus.OFFLINE);
    await this.userRepo.create(user);
    this.logger.info('User created', { userId: id });
    return { id: user.id, username: user.username, status: user.status };
  }

  async getUserById(id: string) {
    const u = await this.userRepo.findById(id);
    if (!u) return null;
    return { id: u.id, username: u.username, status: u.status, lastSeen: u.lastSeen };
  }

  async authenticate(username: string, password: string) {
    const u = await this.userRepo.findByUsername(username);
    if (!u) return null;
  if (!verifyPassword(password, u.passwordHash)) return null;
    const token = sign({ userId: u.id, username: u.username });
    this.logger.info('User authenticated', { userId: u.id });
    return { id: u.id, username: u.username, status: u.status, token };
  }

  async setStatus(userId: string, status: string) {
    await this.userRepo.updateStatus(userId, status);
    this.logger.info('User status updated', { userId, status });
  }

  async listOnlineUsers() {
    return this.userRepo.listOnline();
  }
}
